/**
 * Distributed Retail System
 * Oct 23, 2012 
 */
package comp6231.project.client;

import java.util.ArrayList;
import org.omg.CosNaming.*;

import comp6231.project.frontend.RetailStoreFrontEndInterface;
import comp6231.project.frontend.RetailStoreFrontEndInterfaceHelper;

/**
 * @author dimitri.tiago
 *
 * This class represents a customer. Each customer has a unique customer id.
 * The 1st character of the customer id indicates the location of the customer. 
 */
public class Customer 
{
	private String customerID;
	private String storeRegistry;
	private NamingContextExt namingContextExt;
	
	/**
	 * Default constructor initializes customer object with a customer id. 
	 * @param customerID 6 character customer id. 1st character is a letter indicating the customer location; remaining characters are customer number at store.
	 */
	public Customer(String customerID, String storeRegistry, NamingContextExt namingContextExt)
	{
		this.customerID       = customerID;
		this.storeRegistry    = storeRegistry;
		this.namingContextExt = namingContextExt;
	}
	
	public String Buy(int itemID, int numberOfItems)
	{
		int itemsBought 		  = 0;
		String transactionResult  = null;

		try
		{
			String closestRetailStore = getClosestRetailStore();
				
			RetailStoreFrontEndInterface retailStore = RetailStoreFrontEndInterfaceHelper.narrow(namingContextExt.resolve_str(closestRetailStore));
			itemsBought = retailStore.buyItems(customerID, itemID, numberOfItems);
			transactionResult = (itemsBought == 0)? 
			String.format("%s", "There were not enough items at retail store to satisfy request.") :	
			String.format("Bought %d items at retail store.", itemsBought);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		return transactionResult;
	}

	public String returnItems(int itemID, int numberOfItems)
	{
		int itemsReturned 		  = 0;
		String transactionResult  = null;

		try
		{
			String closestRetailStore = getClosestRetailStore();
			
			RetailStoreFrontEndInterface retailStore = RetailStoreFrontEndInterfaceHelper.narrow(namingContextExt.resolve_str(closestRetailStore));
			itemsReturned = retailStore.returnItems(customerID, itemID, numberOfItems);
			transactionResult = (itemsReturned == 0)? 
			String.format("%s", "Return of items rejected. Returning more items than bought.") :	
			String.format("Returned %d items to retail store.", itemsReturned);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
			
		return transactionResult;
	}	
	
	public String checkStock(int itemID)
	{
		int itemsInStock 		  = 0;
		String transactionResult  = null;

		try 
		{
			String closestRetailStore = getClosestRetailStore();
			RetailStoreFrontEndInterface retailStore = RetailStoreFrontEndInterfaceHelper.narrow(namingContextExt.resolve_str(closestRetailStore));
			itemsInStock = retailStore.checkStock(itemID);
			transactionResult =	String.format("There are %d items in stock for ItemID: %s", itemsInStock, itemID);	
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		return transactionResult;
	}
	
	public String exchangeItems(int boughtItemID, int boughtNumber, int desiredItemID, int desiredNumber)
	{
		int exchangedItems 		  = 0;
		String transactionResult  = null;

		try 
		{
			String closestRetailStore = getClosestRetailStore();
			RetailStoreFrontEndInterface retailStore = RetailStoreFrontEndInterfaceHelper.narrow(namingContextExt.resolve_str(closestRetailStore));
			exchangedItems = retailStore.exchangeItems(customerID, boughtItemID, boughtNumber, desiredItemID, desiredNumber);
			transactionResult = (exchangedItems == 0)? 
					String.format("%s", "Exchange request rejected.") :
					String.format("Exchanged %d of ItemID %d for %d of ItemID % d.", boughtNumber, boughtItemID, desiredNumber, desiredItemID);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		return transactionResult;
	}
	
	/**
	 * This method returns the closes retail store to the customer. 
	 * This is determined through a match between the 1st character of
	 * the customer id and the 1st character of the store name 
	 * (i.e. remote object name in the registry).
	 * @return Returns closes store URL name (i.e. remote object name)
	 */
	private String getClosestRetailStore()
	{
		String closestStore = null;
		
		// obtain code indicating closest store to customer
		String customerLocation	= customerID.substring(0, 1);
		
		// obtain store registry names for retail stores
		ArrayList<String> registeredStores = new ArrayList<String>();
		
		try
		{  
			BindingListHolder bindingListHolder 		= new BindingListHolder();		// obtain names of bindings
			BindingIteratorHolder bindingIteratorHolder = new BindingIteratorHolder();
			namingContextExt.list(1000, bindingListHolder, bindingIteratorHolder);
			
			Binding bindings [] = bindingListHolder.value;								// obtain closest store
			for (int i=0; i < bindings.length; i++) 
			{
	            int lastIx = bindings[i].binding_name.length-1;
	            registeredStores.add(bindings[i].binding_name[lastIx].id);
	        }
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		// determine closest store to customer
		String [] retailStores = registeredStores.toArray(new String [0]);
		for (String store : retailStores)
		{
			String storeLocation = ((store.split("!"))[3]).substring(0, 1);	// obtain first character of store name (indicates location)
			if (storeLocation.equalsIgnoreCase(customerLocation))
			{
				// location match indicates closest store
				return store;
			}
		}
				
		return closestStore;
	}
}
